package gameEngine.agents.observationSystem.analyzer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import org.apache.log4j.Logger;
import gameEngine.agents.observationSystem.samples.Sample;
import gameEngine.agents.teamMateModel.AgentMock;
import gameEngine.agents.teamMateModel.TeamMateModel;
/**
 * Analyzer for Epsilon greedy
 * @author alon
 *
 */
public class EpsilonAnalyzer implements ObservationAnalyzer{

	private TeamMateModel teamateModel;
	/** 
	 * number of rounds that was played for every agent
	 * rounds[0] for agent 1, rounds[1] for agent 2 and so on
	 * */
	//private int expectation[];
	//private int exploration[];
	private HashMap<Integer, Integer> expectation;
	private HashMap<Integer, Integer> exploration;
	Logger log = Logger.getLogger(this.getClass());
	
	/**
	 * CTOR
	 * @param teamateModel
	 * @param numOfAgents
	 */
	public EpsilonAnalyzer(TeamMateModel teamateModel)
	{
		//initialize the round to zeros (no one has played until now)
		expectation=new HashMap<Integer, Integer>();
		exploration=new HashMap<Integer, Integer>();
		for(AgentMock a:teamateModel.getTeamMates()){
			expectation.put(a.getId(), 0);
			exploration.put(a.getId(), 0);
		}
		this.teamateModel=teamateModel;
	}
	
	/**
	 * if agent selected to pass to the best agent by our {@link TeamMateModel}
	 * then he has selected expectation other wise exploration
	 * EGReedy is the ration of exploration out of the total
	 * meaning exploration count divide by sum of exploration and expectation  
	 * @param observation (type of Sample)
	 */
	public void analyze(Sample observation) {
		// TODO Auto-generated method stub
		if(observation == null){ return; }
		//take the agentMok (representation of agent) from the teamateModel 
		int id = observation.getID();
		if(id==teamateModel.getSelf().getId())
			return;
		AgentMock agentMock = teamateModel.getAgentById(id);
		int bestid=getBestAgent(teamateModel);
		int selectedid=observation.getChoose();
		//if agent selected the best agent(in our eyes at list...) then it means
		//he selected expectation
		if(selectedid==bestid){
			expectation.put(id, expectation.get(id)+1);
		}else{//otherwise agent selected exploration 
			exploration.put(id, exploration.get(id)+1);
		}
		double eGreedy=((double)exploration.get(id))/(expectation.get(id)+exploration.get(id));
		agentMock.setAgentEGreedy(eGreedy);
	}
	
	/**
	 * sort team mate model and returns best one according to comperTO method of the AgentMock in model
	 * @param teamMateModel
	 * @return best agent id
	 */
	private int getBestAgent(TeamMateModel teamMateModel){
		ArrayList<AgentMock> agents=new ArrayList<AgentMock>();
		agents.addAll(teamMateModel.getTeamMates());
		//sorts in descending order
		Collections.sort(agents);
		int agent=agents.get(0).getId();
		log.debug("best agent is agent "+agent);
		return agent;
	}
	
	public EpsilonAnalyzer clone(){
		return new EpsilonAnalyzer(teamateModel.clone());
	}
	
	public EpsilonAnalyzer initAnalyzer(TeamMateModel model){
		return new EpsilonAnalyzer(model);
	}
	
}
